//------------------------------------------------------------
//  Filename: x310_fc16_amp.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2024-04-11 19:10
//  Description: 
//   
//  Copyright (C) 2021, UCCHIP, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module x310_fc16_amp #( parameter TCLK_DIV = 199 )
( 
    input  bus_clk,
    input  bus_rst,

    input  [63:0] tx_tdata, input  tx_tlast, input  [3:0] tx_tuser, input  tx_tvalid, output tx_tready,
    output [63:0] rx_tdata, output rx_tlast, output [3:0] rx_tuser, output rx_tvalid, input  rx_tready,

    output dbg_tag_clk,
    output dbg_tag_tx ,
    output dbg_tag_rx
);      

///////////////////////////////////////////////////////////////////////
reg eof;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    eof <= 1'b0;
  end
  else if(tx_tvalid&tx_tready)begin
    eof <= tx_tlast;
  end
end

/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ reg[63:0]  eth_data;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ reg        eth_data_v;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ reg        eth_sof;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire[15:0] mag0, mag1;
/*(* keep = "ture", dont_touch = "true", mark_debug = "true" *)*/ wire       covt_en;


always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    eth_data   <= 64'b0;
    eth_data_v <= 1'b0;
  end
  else if( tx_tvalid & tx_tready ) begin
    eth_data   <= tx_tdata;
    eth_data_v <= 1'b1;
  end
  else begin
    eth_data_v <= 1'b0;
  end
end


wire sof;

assign sof = tx_tvalid & tx_tready & eof;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    eth_sof <= 1'b0;
  end
  else if( tx_tvalid & tx_tready ) begin
    eth_sof <= sof;
  end
end

reg eth_eof;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    eth_eof <= 1'b0;
  end
  else begin
    eth_eof <= tx_tvalid & tx_tready & tx_tlast;
  end
end

reg [2:0]  vef_state;

localparam VEF_IDLE    = 3'd0;
localparam VEF_TIME    = 3'd1;
localparam VEF_PAYLOAD = 3'd2;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    vef_state <= VEF_IDLE;
  end
  else if(eth_eof) begin
    vef_state <= VEF_IDLE;
  end
  else begin
    case(vef_state)
      VEF_IDLE : begin
        if(eth_sof) begin
            if(eth_data[63:61] == 3'b001) vef_state <= VEF_TIME;
            else if (eth_data[63:61] == 3'b000) vef_state <= VEF_PAYLOAD;
        end
      end
      VEF_TIME : begin
        if(eth_data_v) begin
          vef_state <= VEF_PAYLOAD;
        end
      end
      VEF_PAYLOAD : begin
          vef_state <= VEF_PAYLOAD;
      end
      default : begin
         vef_state <= VEF_IDLE;
      end
    endcase // case (vef_state)
  end
end

///////////////////////////////////////////////////////////////////////
wire [15:0] i0, i1;
wire [15:0] q0, q1;
     
wire [15:0] abs_i0, abs_i1;
wire [15:0] abs_q0, abs_q1;
     
wire [14:0] max0, max1;
wire [14:0] min0, min1;

reg  [1:0]  mag_data;
reg         mag_data_vld;
///////////////////////////////////////////////////////////////////////
assign i0       = eth_data[31:16]  ;
assign q0       = eth_data[15:0]   ;

assign abs_i0   = i0[15] ? (~i0+1) : i0;
assign abs_q0   = q0[15] ? (~q0+1) : q0;

assign max0     = abs_i0 > abs_q0 ? abs_i0 : abs_q0;
assign min0     = abs_i0 > abs_q0 ? abs_q0 : abs_i0;

///////////////////////////////////////////////////////////////////////
assign i1       = eth_data[63:48]  ;
assign q1       = eth_data[47:32]  ;

assign abs_i1   = i1[15] ? (~i1+1) : i1;
assign abs_q1   = q1[15] ? (~q1+1) : q1;

assign max1     = abs_i1 > abs_q1 ? abs_i1[14:0] : abs_q1[14:0] ;
assign min1     = abs_i1 > abs_q1 ? abs_q1[14:0] : abs_i1[14:0] ;

assign mag0     = ( vef_state == VEF_PAYLOAD ) ? ( max0 + min0[14:3]) : 'b0;
assign mag1     = ( vef_state == VEF_PAYLOAD ) ? ( max1 + min1[14:3]) : 'b0;
assign covt_en  = ( vef_state == VEF_PAYLOAD ) ? ( eth_data_v       ) : 'b0;
///////////////////////////////////////////////////////////////////////
wire [15:0] thresh_hold = 16'd32;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    mag_data     <= 2'b0;
    mag_data_vld <= 1'b0;
  end
  else begin
    mag_data[0]  <= (mag0 > thresh_hold);
    mag_data[1]  <= (mag1 > thresh_hold);
    mag_data_vld <= covt_en;
  end
end

///////////////////////////////////////////////////////////////////////
reg[7:0]  cntr_div;
wire[7:0] div_parm = TCLK_DIV;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    cntr_div <= 8'b0;
  end
  else begin
    cntr_div <= (cntr_div < div_parm) ? (cntr_div + 1) : 8'b0 ;
  end
end

wire[1:0] mag_2m_sout;
wire      mag_2m_rdy;

///////////////////////////////////////////////////////////////////////
reg  mag_2m_bout;
wire mag_2m_disable;

always @(posedge bus_clk, posedge bus_rst) begin // clk 187.5Mhz
  if(bus_rst) begin
    mag_2m_bout <= 1'b0;
  end
  else if( ~mag_2m_disable ) begin
    if(cntr_div == div_parm[7:1] ) begin      // sample rate 1.875 MSPS
      mag_2m_bout <= mag_2m_sout[1];
    end
    else if(cntr_div == div_parm ) begin
      mag_2m_bout <= mag_2m_sout[0];
    end
  end
end

assign mag_2m_rdy  = (cntr_div == div_parm);
assign dbg_tag_rx  = mag_2m_bout;
///////////////////////////////////////////////////////////////////////
fifo_ampl_8192x2 
mag_fifo_inst0
(
  .clk      ( bus_clk        ),
  .srst     ( bus_rst        ),

  .din      ( mag_data       ),
  .wr_en    ( mag_data_vld   ),

  .dout     ( mag_2m_sout    ),
  .rd_en    ( mag_2m_rdy     ),
  .empty    ( mag_2m_disable )
);

assign rx_tdata  = tx_tdata  ;
assign rx_tuser  = tx_tuser  ;
assign rx_tlast  = tx_tlast  ; 
assign rx_tvalid = tx_tvalid ; 
assign tx_tready = rx_tready ;

///////////////////////////////////////////////////////////////////////
reg dbg_tag_clk0;
reg dbg_tag_clk1;
reg dbg_tag_clk;

///////////////////////////////////////////////////////////////////////
reg[7:0]  tagc_div;
wire[7:0] tagc_parm = 72;

always @(posedge bus_clk, posedge bus_rst) begin
  if(bus_rst) begin
    tagc_div <= 8'b0;
  end
  else begin
    tagc_div <= (tagc_div < tagc_parm) ? (tagc_div + 1) : 8'b0 ;
  end
end

///////////////////////////////////////////////////////////////////////
always @(posedge bus_clk, posedge bus_rst) begin // clk 187.5Mhz
  if(bus_rst) begin
    dbg_tag_clk0 <= 1'b0;
  end
  else if(tagc_div == tagc_parm[7:2] ) begin      // sample rate 1.875 MSPS
    dbg_tag_clk0 <= ~dbg_tag_clk0;
  end
  else if(tagc_div == (tagc_parm[7:1] + tagc_parm[7:2])) begin
    dbg_tag_clk0 <= ~dbg_tag_clk0;
  end
end
///////////////////////////////////////////////////////////////////////
always @(posedge bus_clk, posedge bus_rst) begin // clk 187.5Mhz
  if(bus_rst) begin
    dbg_tag_clk1 <= 1'b0;
  end
  else if(tagc_div == tagc_parm[7:1] ) begin      // sample rate 1.875 MSPS
    dbg_tag_clk1 <= ~dbg_tag_clk1;
  end
  else if(tagc_div == tagc_parm) begin
    dbg_tag_clk1 <= ~dbg_tag_clk1;
  end
end
///////////////////////////////////////////////////////////////////////
always @(posedge bus_clk, posedge bus_rst) begin // clk 187.5Mhz
  if(bus_rst) begin
    dbg_tag_clk <= 1'b0;
  end
  else begin      
    dbg_tag_clk <= dbg_tag_clk0^dbg_tag_clk1;    // clk 2.56MHz
  end
end

wire [3:0] flag_clear ;            //  output [3:0] flag_clear ;
wire [3:0] flag_hold ;             //  output [3:0] flag_hold ;
wire       flag_read ;             //  output       flag_read ;
wire [3:0] flag_data_dig ;         //  input [3:0]  flag_data_dig ;
wire [2:0] iref_r ;                //  output [2:0] iref_r ;
wire [2:0] osc_c ;                 //  output [2:0] osc_c ;
wire [7:0] osc_r ;                 //  output [7:0] osc_r ;
wire       en_rx ;                 //  output       en_rx ;
wire       tx ;                    //  output       tx ;
wire       en_rng ;                //  output       en_rng ;
wire       clk ;                   //  input        clk ;
wire       clk_rng ;               //  input        clk_rng ;
wire       rstn ;                  //  input        rstn ;
wire       rx ;                    //  input        rx ;
wire [1:0] power_det ;             //  output [1:0] power_det ;
wire       power_det_en ;          //  output       power_det_en ;
wire       power_det_out ;         //  input        power_det_out ;
wire[2:0]  pwr_nc ;                //  input [2:0]  pwr_nc ;
wire [3:0] led ;                   //  output [3:0] led ;
wire       en_led_driver ;         //  output       en_led_driver ;
wire       en_led_power ;          //  output       en_led_power ;
wire       power_ok_led ;          //  input        power_ok_led ;
wire       temp_en_ldook ;         //  output       temp_en_ldook ;
wire       temp_en_tmp ;           //  output       temp_en_tmp ;
wire       temp_ldo_ok ;           //  input        temp_ldo_ok ;
wire       temp_clk ;              //  input        temp_clk ;
wire [5:0] otp_addr ;              //  output [5:0] otp_addr ;
wire       otp_pgm ;               //  output       otp_pgm ;
wire       otp_rd ;                //  output       otp_rd ;
wire [7:0] otp_din ;               //  output [7:0] otp_din ;
wire [7:0] otp_dout ;              //  input [7:0]  otp_dout ;
wire       otp_aen ;               //  output       otp_aen ;
wire       otp_aso_rst ;           //  output       otp_aso_rst ;
wire [7:0] otp_pgm_state ;         //  input [7:0]  otp_pgm_state ;
wire       otp_pre ;               //  output       otp_pre ;
wire       otp_ch ;                //  output       otp_ch ;
wire       otp_sen ;               //  output       otp_sen ;
wire       otp_vpp_en ;            //  output       otp_vpp_en ;
wire       vinit ;                 //  output       vinit ;
wire [2:0] nc ;                    //  output [2:0] nc ;

assign clk  = dbg_tag_clk;
assign rx   = dbg_tag_rx;
assign rstn = ~bus_rst;
assign dbg_tag_tx = tx;

assign flag_data_dig  = 'b0;       //  input [3:0]  flag_data_dig ;
assign clk_rng        = 'b0 ;      //  input        clk_rng ;
assign power_ok_led   = 'b0 ;      //  input        power_ok_led ;
assign temp_ldo_ok    = 'b0 ;      //  input        temp_ldo_ok ;
assign temp_clk       = 'b0 ;      //  input        temp_clk ;
assign otp_dout       = 'b0 ;      //  input [7:0]  otp_dout ;
assign otp_pgm_state  = 'b0 ;      //  input [7:0]  otp_pgm_state ;

tag_top 
tag_top_inst0(
  .flag_clear    ( flag_clear    ) ,
  .flag_hold     ( flag_hold     ) ,
  .flag_read     ( flag_read     ) ,
  .flag_data_dig ( flag_data_dig ) ,
  .iref_r        ( iref_r        ) ,
  .osc_c         ( osc_c         ) ,
  .osc_r         ( osc_r         ) ,
  .en_rx         ( en_rx         ) ,
  .tx            ( tx            ) ,
  .en_rng        ( en_rng        ) ,
  .clk           ( clk           ) ,
  .clk_rng       ( clk_rng       ) ,
  .rstn          ( rstn          ) ,
  .rx            ( rx            ) ,
  .power_det     ( power_det     ) ,
  .power_det_en  ( power_det_en  ) ,
  .power_det_out ( power_det_out ) ,
  .pwr_nc        ( pwr_nc        ) ,
  .led           ( led           ) ,
  .en_led_driver ( en_led_driver ) ,
  .en_led_power  ( en_led_power  ) ,
  .power_ok_led  ( power_ok_led  ) ,
  .temp_en_ldook ( temp_en_ldook ) ,
  .temp_en_tmp   ( temp_en_tmp   ) ,
  .temp_ldo_ok   ( temp_ldo_ok   ) ,
  .temp_clk      ( temp_clk      ) ,
  .otp_addr      ( otp_addr      ) ,
  .otp_pgm       ( otp_pgm       ) ,
  .otp_rd        ( otp_rd        ) ,
  .otp_din       ( otp_din       ) ,
  .otp_dout      ( otp_dout      ) ,
  .otp_aen       ( otp_aen       ) ,
  .otp_aso_rst   ( otp_aso_rst   ) ,
  .otp_pgm_state ( otp_pgm_state ) ,
  .otp_pre       ( otp_pre       ) ,
  .otp_ch        ( otp_ch        ) ,
  .otp_sen       ( otp_sen       ) ,
  .otp_vpp_en    ( otp_vpp_en    ) ,
  .vinit         ( vinit         ) ,
  .nc            ( nc            ) 
);



endmodule

